<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>学生座位表调整工具</title>
    <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
    <script src="https://cdn.sheetjs.com/xlsx-0.19.3/package/dist/xlsx.full.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
        }

        body {
            background: linear-gradient(135deg, #f5f7fa 0%, #e4edf5 100%);
            min-height: 100vh;
            padding: 20px;
            color: #333;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
        }

        header {
            text-align: center;
            padding: 25px 0;
            margin-bottom: 30px;
            background: linear-gradient(90deg, #1a73e8, #0d47a1);
            color: white;
            border-radius: 12px;
            box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
        }

        h1 {
            font-size: 2.6rem;
            margin-bottom: 10px;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.25);
        }

        .subtitle {
            font-size: 1.15rem;
            opacity: 0.92;
            letter-spacing: 0.5px;
        }

        .toolbar {
            display: flex;
            justify-content: space-between;
            flex-wrap: wrap;
            gap: 18px;
            padding: 22px;
            background: linear-gradient(135deg, #ffffff, #f8f9fa);
            border-radius: 12px;
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
            margin-bottom: 30px;
            border: 1px solid #e1e5eb;
        }

        .btn-group {
            display: flex;
            gap: 14px;
            flex-wrap: wrap;
        }

        .btn {
            padding: 14px 28px;
            background: linear-gradient(135deg, #4285f4, #1a73e8);
            color: white;
            border: none;
            border-radius: 50px;
            cursor: pointer;
            font-weight: 600;
            font-size: 1.05rem;
            transition: all 0.3s ease;
            box-shadow: 0 5px 12px rgba(66, 133, 244, 0.35);
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .btn:hover {
            transform: translateY(-4px);
            box-shadow: 0 8px 15px rgba(66, 133, 244, 0.45);
        }

        .btn:active {
            transform: translateY(1px);
            box-shadow: 0 3px 8px rgba(66, 133, 244, 0.35);
        }

        .btn-random {
            background: linear-gradient(135deg, #fbbc05, #e6a000);
            box-shadow: 0 5px 12px rgba(251, 188, 5, 0.35);
        }

        .btn-reset {
            background: linear-gradient(135deg, #ea4335, #d32d20);
            box-shadow: 0 5px 12px rgba(234, 67, 53, 0.35);
        }

        .btn-pdf {
            background: linear-gradient(135deg, #e53935, #b71c1c);
            box-shadow: 0 5px 12px rgba(229, 57, 53, 0.35);
        }

        .btn-excel {
            background: linear-gradient(135deg, #0f9d58, #0b8043);
            box-shadow: 0 5px 12px rgba(15, 157, 88, 0.35);
        }

        .file-upload {
            position: relative;
            display: inline-block;
            overflow: hidden;
            border-radius: 50px;
            box-shadow: 0 4px 10px rgba(66, 133, 244, 0.3);
        }

        .file-upload input {
            position: absolute;
            left: 0;
            top: 0;
            opacity: 0;
            width: 100%;
            height: 100%;
            cursor: pointer;
        }

        /* 教室布局 */
        .classroom-container {
            background: white;
            border-radius: 14px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12);
            overflow: hidden;
            margin-bottom: 30px;
            border: 1px solid #e9ecef;
        }

        .classroom-header {
            background: linear-gradient(135deg, #6a11cb, #2575fc);
            color: white;
            text-align: center;
            padding: 15px;
            font-weight: bold;
            font-size: 1.2rem;
        }

        .classroom {
            display: grid;
            gap: 14px;
            padding: 25px;
        }

        /* 讲台容器 */
        .teacher-desk-container {
            grid-column: 1 / -1;
            display: flex;
            justify-content: center;
            margin-bottom: 25px;
        }

        /* 讲台 */
        .teacher-desk {
            width: 300px;
            background: linear-gradient(135deg, #8e2de2, #4a00e0);
            border-radius: 10px;
            display: flex;
            justify-content: center;
            align-items: center;
            color: white;
            font-weight: bold;
            font-size: 1.3rem;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
            text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3);
            padding: 15px;
        }

        /* 普通座位样式 */
        .seat {
            height: 120px;
            border-radius: 10px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            padding: 12px;
            cursor: move;
            transition: all 0.3s ease;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
            position: relative;
            overflow: hidden;
            border: 2px solid transparent;
        }

        .seat.empty {
            background: linear-gradient(135deg, #f0f0f0, #e0e0e0);
            color: #999;
        }

        .seat.male {
            background: linear-gradient(135deg, #64b5f6, #42a5f5);
            border-color: #bbdefb;
        }

        .seat.female {
            background: linear-gradient(135deg, #f48fb1, #f06292);
            border-color: #f8bbd0;
        }

        .seat.dragging {
            opacity: 0.7;
            transform: scale(0.95);
            box-shadow: 0 0 20px rgba(66, 133, 244, 0.7);
            z-index: 10;
        }

        .seat.drag-over {
            background-color: rgba(255, 235, 59, 0.4) !important;
            transform: scale(1.06);
            border-color: #ffc107 !important;
        }

        /* 位置信息样式 */
        .seat-position {
            position: absolute;
            top: 8px;
            left: 8px;
            font-size: 0.85rem;
            font-weight: 700;
            color: #555;
            background: rgba(255, 255, 255, 0.7);
            border-radius: 20px;
            width: 24px;
            height: 24px;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        /* 姓名样式 */
        .student-name {
            font-size: 1.25rem;
            font-weight: 700;
            margin-bottom: 8px;
            text-align: center;
            width: 100%;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            padding: 0 5px;
        }

        /* 性别容器 */
        .student-details {
            display: flex;
            justify-content: center;
            gap: 8px;
            width: 100%;
            padding: 0 5px;
        }

        /* 性别样式 */
        .student-gender {
            font-size: 0.9rem;
            padding: 3px 10px;
            border-radius: 20px;
            background: rgba(255, 255, 255, 0.4);
            font-weight: 600;
            white-space: nowrap;
        }

        .instructions {
            background: linear-gradient(135deg, #ffffff, #f8f9fa);
            padding: 28px;
            border-radius: 14px;
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.08);
            margin-top: 25px;
            border: 1px solid #e9ecef;
        }

        .instructions h2 {
            color: #1a73e8;
            margin-bottom: 20px;
            font-size: 1.6rem;
            text-align: center;
            padding-bottom: 12px;
            border-bottom: 2px solid #e0e7ff;
        }

        .instructions ul {
            padding-left: 30px;
            line-height: 1.85;
        }

        .instructions li {
            margin-bottom: 14px;
            font-size: 1.05rem;
            position: relative;
        }

        .instructions li:before {
            content: "•";
            color: #1a73e8;
            font-weight: bold;
            display: inline-block;
            width: 1em;
            margin-left: -1em;
            font-size: 1.3rem;
        }

        .status-bar {
            display: flex;
            justify-content: space-between;
            padding: 18px 25px;
            background: linear-gradient(135deg, #ffffff, #f8f9fa);
            border-radius: 14px;
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.08);
            margin-top: 25px;
            font-size: 1rem;
            border: 1px solid #e9ecef;
            flex-wrap: wrap;
            gap: 12px;
        }

        .stats-container {
            display: flex;
            flex-wrap: wrap;
            gap: 12px;
            width: 100%;
            justify-content: center;
        }

        .stats-box {
            background: rgba(255, 255, 255, 0.7);
            border-radius: 10px;
            padding: 12px 20px;
            min-width: 160px;
            text-align: center;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
        }

        .stats-title {
            font-size: 0.9rem;
            color: #666;
            margin-bottom: 6px;
        }

        .stats-value {
            font-size: 1.4rem;
            font-weight: bold;
            color: #1a73e8;
        }

        .stats-box.male .stats-value {
            color: #4285f4;
        }

        .stats-box.female .stats-value {
            color: #f06292;
        }

        .stats-box.empty .stats-value {
            color: #666;
        }

        .stats-box.total .stats-value {
            color: #0f9d58;
        }

        .notification {
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 15px 25px;
            background: #4CAF50;
            color: white;
            border-radius: 8px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
            z-index: 1000;
            transform: translateX(150%);
            transition: transform 0.3s ease;
        }

        .notification.show {
            transform: translateX(0);
        }

        .notification.error {
            background: #f44336;
        }

        /* 自定义布局弹窗 */
        .modal {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 2000;
            opacity: 0;
            pointer-events: none;
            transition: opacity 0.3s ease;
        }

        .modal.active {
            opacity: 1;
            pointer-events: auto;
        }

        .modal-content {
            background-color: white;
            border-radius: 12px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
            max-width: 400px;
            width: 90%;
            padding: 30px;
            transform: scale(0.9);
            transition: transform 0.3s ease;
        }

        .modal.active .modal-content {
            transform: scale(1);
        }

        .modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 1px solid #eee;
        }

        .modal-title {
            font-size: 1.5rem;
            font-weight: bold;
            color: #1a73e8;
        }

        .close-modal {
            font-size: 1.8rem;
            cursor: pointer;
            color: #666;
            transition: color 0.3s ease;
        }

        .close-modal:hover {
            color: #333;
        }

        .form-group {
            margin-bottom: 20px;
        }

        .form-group label {
            display: block;
            font-size: 1.1rem;
            margin-bottom: 8px;
            color: #333;
            font-weight: 500;
        }

        .form-group input {
            width: 100%;
            padding: 12px 15px;
            border: 1px solid #ddd;
            border-radius: 8px;
            font-size: 1rem;
            transition: border-color 0.3s ease;
        }

        .form-group input:focus {
            border-color: #1a73e8;
            outline: none;
            box-shadow: 0 0 0 2px rgba(26, 115, 232, 0.2);
        }

        .modal-footer {
            display: flex;
            justify-content: flex-end;
            gap: 15px;
            margin-top: 20px;
            padding-top: 20px;
            border-top: 1px solid #eee;
        }

        .btn-cancel {
            background: linear-gradient(135deg, #f0f0f0, #e0e0e0);
            color: #333;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
        }

        .btn-cancel:hover {
            background: linear-gradient(135deg, #e0e0e0, #d0d0d0);
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
        }

        @media (max-width: 900px) {
            .classroom {
                gap: 12px;
            }

            .toolbar {
                flex-direction: column;
                align-items: center;
            }

            .btn-group {
                width: 100%;
                justify-content: center;
            }

            .status-bar {
                flex-wrap: wrap;
                gap: 12px;
                justify-content: center;
            }

            .stats-container {
                flex-wrap: wrap;
            }

            .student-name {
                font-size: 1.1rem;
            }

            .student-gender {
                font-size: 0.8rem;
                padding: 2px 8px;
            }
        }

        @media (max-width: 600px) {
            .classroom {
                grid-template-columns: repeat(2, 1fr);
            }

            .teacher-desk {
                width: 100%;
            }

            header h1 {
                font-size: 2rem;
            }

            .btn {
                padding: 12px 20px;
                font-size: 0.95rem;
            }

            .stats-container {
                flex-direction: column;
                align-items: center;
            }

            .stats-box {
                width: 100%;
            }

            .modal-content {
                max-width: 90%;
                padding: 20px;
            }

            .seat {
                height: 110px;
            }

            .student-name {
                font-size: 1rem;
            }
        }
    </style>
</head>

<body>
    <div id="app"></div>

    <script type="module">
        const { createApp, ref, computed, onMounted, watch } = Vue;

        const app = createApp({
            setup() {
                // 状态变量
                const rows = ref(8);
                const columns = ref(8);
                const newRows = ref(8);
                const newColumns = ref(8);
                const showLayoutModal = ref(false);
                const seats = ref([]);
                const draggedSeat = ref(null);
                const dragOverSeat = ref(null);
                const notificationMessage = ref('');
                const showNotification = ref(false);
                const notificationError = ref(false);

                // 计算属性
                const totalSeats = computed(() => rows.value * columns.value);
                const maleCount = computed(() => seats.value.filter(seat => !seat.isEmpty && seat.gender === '男').length);
                const femaleCount = computed(() => seats.value.filter(seat => !seat.isEmpty && seat.gender === '女').length);
                const studentCount = computed(() => maleCount.value + femaleCount.value);
                const emptyCount = computed(() => totalSeats.value - studentCount.value);

                // 初始化座位
                function initSeats() {
                    seats.value = Array(totalSeats.value).fill().map((_, index) => ({
                        id: index + 1,
                        name: "",
                        gender: "",
                        isEmpty: true
                    }));
                }

                // 从本地存储加载
                function loadFromLocalStorage() {
                    const savedSeats = localStorage.getItem('classroomSeats');
                    const savedLayout = localStorage.getItem('classroomLayout');

                    if (savedLayout) {
                        try {
                            const { r, c } = JSON.parse(savedLayout);
                            if (typeof r === 'number' && typeof c === 'number') {
                                rows.value = r;
                                columns.value = c;
                                newRows.value = r;
                                newColumns.value = c;
                            }
                        } catch (e) {
                            console.error("解析布局数据失败:", e);
                        }
                    }

                    if (savedSeats) {
                        try {
                            const parsedSeats = JSON.parse(savedSeats);
                            if (Array.isArray(parsedSeats) && parsedSeats.length === totalSeats.value) {
                                seats.value = parsedSeats;
                                showNotificationMessage("已加载上次保存的座位表");
                                return true;
                            }
                        } catch (e) {
                            console.error("解析本地存储数据失败:", e);
                        }
                    }
                    return false;
                }

                // 保存到本地存储
                function saveToLocalStorage() {
                    localStorage.setItem('classroomSeats', JSON.stringify(seats.value));
                    localStorage.setItem('classroomLayout', JSON.stringify({
                        r: rows.value,
                        c: columns.value
                    }));
                }

                // 显示通知
                function showNotificationMessage(message, isError = false) {
                    notificationMessage.value = message;
                    notificationError.value = isError;
                    showNotification.value = true;

                    setTimeout(() => {
                        showNotification.value = false;
                    }, 3000);
                }

                // 处理拖拽事件
                function handleDragStart(seat, event) {
                    // 空位不能拖动
                    if (seat.isEmpty) {
                        event.preventDefault();
                        return;
                    }

                    draggedSeat.value = seat;
                    // 添加拖拽数据以确保拖拽功能正常工作
                    event.dataTransfer.setData('text/plain', seat.id.toString());
                    // 延迟添加拖拽类以确保视觉效果正确
                    setTimeout(() => {
                        const element = event.target.closest('.seat');
                        if (element) element.classList.add('dragging');
                    }, 0);
                }

                function handleDragEnter(seat) {
                    if (!draggedSeat.value || draggedSeat.value.id === seat.id) return;
                    dragOverSeat.value = seat;
                }

                function handleDragLeave(seat) {
                    if (dragOverSeat.value?.id === seat.id) {
                        dragOverSeat.value = null;
                    }
                }

                function handleDrop(targetSeat) {
                    if (!draggedSeat.value || draggedSeat.value.id === targetSeat.id) return;

                    if (targetSeat.isEmpty) {
                        // 移动到空位
                        targetSeat.name = draggedSeat.value.name;
                        targetSeat.gender = draggedSeat.value.gender;
                        targetSeat.isEmpty = false;

                        // 清空原座位
                        draggedSeat.value.name = "";
                        draggedSeat.value.gender = "";
                        draggedSeat.value.isEmpty = true;
                    } else {
                        // 交换座位
                        [draggedSeat.value.name, targetSeat.name] = [targetSeat.name, draggedSeat.value.name];
                        [draggedSeat.value.gender, targetSeat.gender] = [targetSeat.gender, draggedSeat.value.gender];
                    }

                    dragOverSeat.value = null;
                    saveToLocalStorage();
                    showNotificationMessage("座位调整成功！");
                }

                function handleDragEnd(event) {
                    // 移除所有拖拽相关的类
                    const elements = document.querySelectorAll('.seat');
                    elements.forEach(el => {
                        el.classList.remove('dragging', 'drag-over');
                    });

                    draggedSeat.value = null;
                    dragOverSeat.value = null;
                }

                // 处理Excel导入
                function handleExcelImport(e) {
                    const file = e.target.files[0];
                    if (!file) return;

                    // 重置文件输入，允许重复选择同一文件
                    const input = document.getElementById('excel-file');
                    if (input) input.value = '';

                    const reader = new FileReader();
                    reader.onload = function (e) {
                        try {
                            const data = new Uint8Array(e.target.result);
                            const workbook = XLSX.read(data, { type: 'array' });

                            // 获取第一个工作表
                            const worksheet = workbook.Sheets[workbook.SheetNames[0]];
                            const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });

                            // 处理数据
                            const students = [];
                            let nameIndex = -1, genderIndex = -1;

                            // 查找列索引
                            if (jsonData.length > 0) {
                                const headerRow = jsonData[0];
                                nameIndex = headerRow.findIndex(cell =>
                                    cell && String(cell).toLowerCase().includes("姓名") ||
                                    String(cell).toLowerCase().includes("名字")
                                );
                                genderIndex = headerRow.findIndex(cell =>
                                    cell && String(cell).toLowerCase().includes("性别")
                                );

                                // 如果未找到姓名列，尝试使用第一列
                                if (nameIndex === -1) {
                                    nameIndex = 0;
                                    showNotificationMessage("未找到'姓名'列，将使用第一列作为姓名", false);
                                }
                            }

                            // 处理学生数据
                            for (let i = 1; i < jsonData.length; i++) {
                                const row = jsonData[i];
                                if (!row || row.length === 0) continue;

                                const student = {
                                    name: nameIndex >= 0 && row[nameIndex] ? String(row[nameIndex]).trim() : "",
                                    gender: genderIndex >= 0 && row[genderIndex] ? String(row[genderIndex]).trim() : ""
                                };

                                if (student.name) {
                                    students.push(student);
                                }
                            }

                            if (students.length === 0) {
                                showNotificationMessage("Excel中没有找到有效的学生数据，请检查格式", true);
                                return;
                            }

                            // 重置座位并填充新数据
                            initSeats();

                            // 填充学生数据
                            let seatIndex = 0;
                            students.forEach(student => {
                                if (seatIndex < seats.value.length) {
                                    seats.value[seatIndex].name = student.name;
                                    seats.value[seatIndex].gender = student.gender;
                                    seats.value[seatIndex].isEmpty = false;
                                    seatIndex++;
                                }
                            });

                            saveToLocalStorage();
                            showNotificationMessage(`成功导入 ${students.length} 名学生数据`);
                        } catch (error) {
                            console.error("Excel导入错误:", error);
                            showNotificationMessage(`Excel导入失败: ${error.message}`, true);
                        }
                    };

                    reader.onerror = function () {
                        showNotificationMessage("文件读取失败，请尝试其他文件", true);
                    };

                    reader.readAsArrayBuffer(file);
                }

                // 导出Excel
                function exportToExcel() {
                    try {
                        // 准备数据
                        const data = [];

                        // 添加标题行
                        data.push(['学生座位表（姓名）']);
                        data.push([]); // 空行

                        // 添加普通座位区标题
                        data.push(['普通座位区']);

                        // 添加列标题
                        const columnHeaders = ['行\\列'];
                        for (let col = 1; col <= columns.value; col++) {
                            columnHeaders.push(`第${col}列`);
                        }
                        data.push(columnHeaders);

                        // 添加每行数据
                        for (let row = 0; row < rows.value; row++) {
                            const rowData = [`第${row + 1}行`];

                            for (let col = 0; col < columns.value; col++) {
                                const seatIndex = row * columns.value + col;
                                const seat = seats.value[seatIndex];
                                rowData.push(seat?.isEmpty ? '空' : seat?.name || '空');
                            }

                            data.push(rowData);
                        }

                        // 创建工作簿
                        const ws = XLSX.utils.aoa_to_sheet(data);
                        const wb = XLSX.utils.book_new();
                        XLSX.utils.book_append_sheet(wb, ws, "座位表");

                        // 设置列宽
                        const colWidths = [{ wch: 8 }];
                        for (let i = 1; i <= columns.value; i++) {
                            colWidths.push({ wch: 12 });
                        }
                        ws['!cols'] = colWidths;

                        // 合并标题单元格
                        ws['!merges'] = [
                            { s: { r: 0, c: 0 }, e: { r: 0, c: columns.value } },
                            { s: { r: 2, c: 0 }, e: { r: 2, c: columns.value } }
                        ];

                        // 导出
                        XLSX.writeFile(wb, "学生座位表.xlsx");
                        showNotificationMessage("Excel导出成功！");
                    } catch (error) {
                        console.error("导出Excel时出错:", error);
                        showNotificationMessage("导出Excel失败，请重试", true);
                    }
                }

                // 随机排列
                function randomizeSeats() {
                    const nonEmptySeats = seats.value.filter(seat => !seat.isEmpty);

                    if (nonEmptySeats.length === 0) {
                        showNotificationMessage("没有学生数据，无法随机排列", true);
                        return;
                    }

                    // 随机打乱顺序
                    for (let i = nonEmptySeats.length - 1; i > 0; i--) {
                        const j = Math.floor(Math.random() * (i + 1));
                        [nonEmptySeats[i].name, nonEmptySeats[j].name] = [nonEmptySeats[j].name, nonEmptySeats[i].name];
                        [nonEmptySeats[i].gender, nonEmptySeats[j].gender] = [nonEmptySeats[j].gender, nonEmptySeats[i].gender];
                    }

                    saveToLocalStorage();
                    showNotificationMessage("座位随机排列完成");
                }

                // 重置座位
                function resetSeats() {
                    if (confirm("确定要重置所有座位吗？这将清除所有学生数据。")) {
                        initSeats();
                        saveToLocalStorage();
                        showNotificationMessage("座位表已重置");
                    }
                }

                // 导出PDF（只包含座位）
                function exportToPdf() {
                    const classroomElement = document.getElementById('classroom');

                    if (!classroomElement) {
                        showNotificationMessage("找不到座位表内容", true);
                        return;
                    }

                    showNotificationMessage("正在生成PDF，请稍候...");

                    // 创建临时容器
                    const tempContainer = document.createElement('div');
                    tempContainer.style.width = '100%';
                    tempContainer.style.background = '#fff';
                    tempContainer.style.padding = '20px';
                    tempContainer.style.boxSizing = 'border-box';

                    // 克隆座位区域
                    const clonedContent = classroomElement.cloneNode(true);

                    // 调整样式
                    clonedContent.style.gap = '8px';
                    clonedContent.style.padding = '15px';

                    // 调整座位样式
                    const allSeats = clonedContent.querySelectorAll('.seat');
                    allSeats.forEach(seat => {
                        seat.style.height = '70px';
                        seat.style.padding = '8px';

                        const nameElement = seat.querySelector('.student-name');
                        if (nameElement) {
                            nameElement.style.fontSize = '12px';
                            nameElement.style.fontWeight = 'bold';
                            nameElement.style.color = '#000';
                        }

                        const genderElements = seat.querySelectorAll('.student-gender');
                        genderElements.forEach(el => {
                            el.style.fontSize = '10px';
                            el.style.color = '#000';
                        });
                    });

                    // 添加标题
                    const title = document.createElement('h2');
                    title.style.textAlign = 'center';
                    title.style.margin = '0 0 20px 0';
                    title.style.fontSize = '18px';
                    title.textContent = '学生座位表';

                    // 组装临时容器
                    tempContainer.appendChild(title);
                    tempContainer.appendChild(clonedContent);

                    // 添加到页面但隐藏
                    tempContainer.style.position = 'absolute';
                    tempContainer.style.top = '-10000px';
                    tempContainer.style.left = '-10000px';
                    document.body.appendChild(tempContainer);

                    // 生成PDF
                    const useLandscape = columns.value > 8;
                    const pdf = new jspdf.jsPDF({
                        orientation: useLandscape ? 'landscape' : 'portrait',
                        unit: 'mm',
                        format: 'a4'
                    });

                    html2canvas(tempContainer, {
                        scale: 2, // 降低分辨率以减少文件大小
                        useCORS: true,
                        logging: false,
                        scrollY: -window.scrollY,
                        windowWidth: tempContainer.offsetWidth,
                        letterRendering: true,
                        backgroundColor: null
                    }).then(canvas => {
                        const imgWidth = useLandscape ? 270 : 190;
                        const imgHeight = canvas.height * imgWidth / canvas.width;
                        const marginX = useLandscape ? 10 : 10;
                        const marginY = 10;

                        // 处理多页
                        const pageHeight = useLandscape ? 180 : 270;
                        let position = marginY;

                        if (imgHeight > pageHeight - marginY * 2) {
                            let heightLeft = imgHeight;
                            let startY = 0;

                            while (heightLeft > 0) {
                                const pageHeightCurrent = heightLeft > pageHeight ? pageHeight : heightLeft;

                                const canvasData = canvas.getContext('2d').getImageData(
                                    0,
                                    startY,
                                    canvas.width,
                                    canvas.height * pageHeightCurrent / imgHeight
                                );

                                const newCanvas = document.createElement('canvas');
                                newCanvas.width = canvas.width;
                                newCanvas.height = canvas.height * pageHeightCurrent / imgHeight;
                                newCanvas.getContext('2d').putImageData(canvasData, 0, 0);

                                const imgData = newCanvas.toDataURL('image/jpeg', 0.7); // 使用JPEG格式并降低质量

                                pdf.addImage(imgData, 'JPEG', marginX, position, imgWidth, pageHeightCurrent);

                                heightLeft -= pageHeightCurrent;
                                startY += canvas.height * pageHeightCurrent / imgHeight;
                                position = marginY;

                                if (heightLeft > 0) {
                                    pdf.addPage();
                                }
                            }
                        } else {
                            const imgData = canvas.toDataURL('image/jpeg', 0.7); // 使用JPEG格式并降低质量
                            pdf.addImage(imgData, 'JPEG', marginX, marginY, imgWidth, imgHeight);
                        }

                        pdf.save('学生座位表.pdf');
                        document.body.removeChild(tempContainer);
                        showNotificationMessage("PDF导出成功！");
                    }).catch(error => {
                        console.error("PDF导出错误:", error);
                        showNotificationMessage("PDF导出失败，请重试", true);
                        document.body.removeChild(tempContainer);
                    });
                }

                // 布局设置
                function confirmLayout() {
                    if (isNaN(newRows.value) || isNaN(newColumns.value) ||
                        newRows.value < 1 || newColumns.value < 1 ||
                        newRows.value > 20 || newColumns.value > 20) {
                        showNotificationMessage("请输入有效的行数和列数（1-20之间）", true);
                        return;
                    }

                    // 保存当前学生数据
                    const currentStudents = seats.value.filter(seat => !seat.isEmpty);

                    // 更新布局
                    rows.value = newRows.value;
                    columns.value = newColumns.value;

                    // 初始化新座位
                    initSeats();

                    // 恢复学生数据
                    let seatIndex = 0;
                    currentStudents.forEach(student => {
                        if (seatIndex < seats.value.length) {
                            seats.value[seatIndex].name = student.name;
                            seats.value[seatIndex].gender = student.gender;
                            seats.value[seatIndex].isEmpty = false;
                            seatIndex++;
                        }
                    });

                    saveToLocalStorage();
                    showLayoutModal.value = false;
                    showNotificationMessage(`座位布局已更新为 ${rows.value}×${columns.value}`);
                }

                function closeLayoutModalOnOutside(e) {
                    if (e.target === e.currentTarget) {
                        showLayoutModal.value = false;
                    }
                }

                // 初始化
                onMounted(() => {
                    initSeats();
                    loadFromLocalStorage();

                    // 监听布局变化
                    watch([rows, columns], () => {
                        initSeats();
                    });
                });

                return {
                    rows,
                    columns,
                    newRows,
                    newColumns,
                    showLayoutModal,
                    seats,
                    draggedSeat,
                    dragOverSeat,
                    notificationMessage,
                    showNotification,
                    notificationError,
                    totalSeats,
                    maleCount,
                    femaleCount,
                    studentCount,
                    emptyCount,
                    handleExcelImport,
                    handleDragStart,
                    handleDragEnter,
                    handleDragLeave,
                    handleDrop,
                    handleDragEnd,
                    exportToExcel,
                    randomizeSeats,
                    resetSeats,
                    exportToPdf,
                    confirmLayout,
                    closeLayoutModalOnOutside,
                    showNotificationMessage
                };
            },
            template: `
                <div class="container">
                    <div class="notification" :class="{ show: showNotification, error: notificationError }">{{ notificationMessage }}</div>

                    <header>
                        <h1>学生座位表调整工具</h1>
                        <div class="subtitle">自定义布局 | 拖拽交换 | Excel导入/导出</div>
                    </header>

                    <div class="toolbar">
                        <div class="file-upload">
                            <button class="btn">
                                <i>📊</i> 导入Excel
                                <input type="file" id="excel-file" accept=".xlsx, .xls" @change="handleExcelImport">
                            </button>
                        </div>

                        <div class="btn-group">
                            <button class="btn btn-random" @click="randomizeSeats">
                                <i>🔀</i> 随机排列
                            </button>
                            <button class="btn btn-reset" @click="resetSeats">
                                <i>🔄</i> 重置座位
                            </button>
                            <button class="btn btn-pdf" @click="exportToPdf">
                                <i>📄</i> 导出PDF
                            </button>
                            <button class="btn btn-excel" @click="exportToExcel">
                                <i>📤</i> 导出Excel
                            </button>
                            <button class="btn" @click="showLayoutModal = true">
                                <i>🔲</i> 设置布局
                            </button>
                        </div>
                    </div>

                    <div class="classroom-container" id="print-target">
                        <div class="classroom-header">教室座位布局（<span id="layout-info">{{ rows }}×{{ columns }}标准座位</span>）</div>
                        <div class="classroom" id="classroom" :style="{ gridTemplateColumns: \`repeat(\${columns}, 1fr)\` }">
                            <!-- 讲台 -->
                            <div class="teacher-desk-container">
                                <div class="teacher-desk">讲台</div>
                            </div>
                            
                            <!-- 普通座位 -->
                            <div 
                                class="seat" 
                                :class="{ 
                                    empty: seat.isEmpty, 
                                    male: !seat.isEmpty && seat.gender === '男', 
                                    female: !seat.isEmpty && seat.gender === '女',
                                    dragging: draggedSeat?.id === seat.id,
                                    'drag-over': dragOverSeat?.id === seat.id
                                }"
                                :data-id="seat.id"
                                draggable="true"
                                @dragstart="handleDragStart(seat, $event)"
                                @dragover.prevent
                                @dragenter.prevent="handleDragEnter(seat)"
                                @dragleave="handleDragLeave(seat)"
                                @drop.prevent="handleDrop(seat)"
                                @dragend="handleDragEnd"
                                v-for="seat in seats" :key="seat.id"
                            >
                                <div class="seat-position">{{ seat.id }}</div>
                                <div class="student-name">{{ seat.isEmpty ? '空' : seat.name }}</div>
                                <template v-if="!seat.isEmpty">
                                    <div class="student-details">
                                        <div class="student-gender">{{ seat.gender }}</div>
                                    </div>
                                </template>
                            </div>
                        </div>
                    </div>

                    <div class="status-bar">
                        <div class="stats-container">
                            <div class="stats-box male">
                                <div class="stats-title">男生人数</div>
                                <div class="stats-value">{{ maleCount }}</div>
                            </div>
                            <div class="stats-box female">
                                <div class="stats-title">女生人数</div>
                                <div class="stats-value">{{ femaleCount }}</div>
                            </div>
                            <div class="stats-box empty">
                                <div class="stats-title">空座位数</div>
                                <div class="stats-value">{{ emptyCount }}</div>
                            </div>
                            <div class="stats-box total">
                                <div class="stats-title">学生总数</div>
                                <div class="stats-value">{{ studentCount }}</div>
                            </div>
                            <div class="stats-box">
                                <div class="stats-title">总座位数</div>
                                <div class="stats-value">{{ totalSeats }}</div>
                            </div>
                        </div>
                    </div>

                    <div class="instructions">
                        <h2>使用说明</h2>
                        <ul>
                            <li><strong>座位布局</strong>：讲台居中，下方为自定义布局（默认8×8，共64个座位）</li>
                            <li><strong>Excel导入</strong>：点击"导入Excel"按钮，选择包含学生信息的Excel文件（包含"姓名"、"性别"列）</li>
                            <li><strong>Excel导出</strong>：点击"导出Excel"按钮将当前座位表导出为Excel文件</li>
                            <li><strong>拖拽交换</strong>：拖动学生座位到另一个座位进行交换（可以与空位交换）</li>
                            <li><strong>随机排列</strong>：点击"随机排列"按钮打乱当前学生座位顺序</li>
                            <li><strong>本地存储</strong>：座位表状态会自动保存，刷新页面不会丢失数据</li>
                            <li><strong>重置座位</strong>：点击"重置"按钮清空所有座位</li>
                            <li><strong>导出PDF</strong>：点击"导出PDF"按钮生成当前座位表的PDF文件</li>
                            <li><strong>设置布局</strong>：点击"设置布局"按钮自定义普通座位区的行数和列数</li>
                        </ul>
                    </div>

                    <!-- 自定义布局弹窗 -->
                    <div class="modal" :class="{ active: showLayoutModal }" @click="closeLayoutModalOnOutside">
                        <div class="modal-content" @click.stop>
                            <div class="modal-header">
                                <div class="modal-title">设置座位布局</div>
                                <div class="close-modal" @click="showLayoutModal = false">&times;</div>
                            </div>
                            <div class="modal-body">
                                <div class="form-group">
                                    <label for="rows">行数：</label>
                                    <input type="number" id="rows" v-model.number="newRows" min="1" max="20" placeholder="输入行数">
                                </div>
                                <div class="form-group">
                                    <label for="columns">列数：</label>
                                    <input type="number" id="columns" v-model.number="newColumns" min="1" max="20" placeholder="输入列数">
                                </div>
                            </div>
                            <div class="modal-footer">
                                <button class="btn btn-cancel" @click="showLayoutModal = false">取消</button>
                                <button class="btn" @click="confirmLayout">确认</button>
                            </div>
                        </div>
                    </div>
                </div>
            `
        });

        app.mount('#app');
    </script>
</body>

</html>